using System;
using System.Collections.Generic;
using FlowCanvas.Nodes;
using UnityEngine;
using Yoozoo.Core.Extensions.CSharp;
using Yoozoo.Gta.Common;
using Yoozoo.Libs;
using Yoozoo.Managers;
using Random = UnityEngine.Random;

namespace Gameplay.PVE.Survivor
{
    public abstract class BubbleEvent : IClass
    {
        public int UnitID;
        protected float bubbleTimer;

        public EBubbleEventType BubbleType { get; private set; }

        public HeroBubbleEventConfig Cfg { get; private set; }
        public HeroBubbleGroupConfig GroupConfig { get; private set; }

        public virtual void InitData(int unitID, HeroBubbleEventConfig EventCfg, HeroBubbleGroupConfig cfg)
        {
            UnitID = unitID;
            Cfg = EventCfg;
            GroupConfig = cfg;
            if (this.Cfg == null)
            {
                BubbleType = EBubbleEventType.None;
            }
            else
            {
                this.BubbleType = (EBubbleEventType)this.Cfg.type;
            }
        }

        public abstract void OnTrigger(params object[] args);

        public virtual void Bubble()
        {
            var battleUnit = UnitManager.Instance.GetUnitById(UnitID);
            if (battleUnit == null)
            {
                return;
            }

            if (Cfg.cd != 0)
            {
                if (TimeManager.time - bubbleTimer < Cfg.cd)
                {
                    return;
                }
            }

            if (Cfg.probability > 0)
            {
                var value = (Random.Range(0, 100f) * 0.01);
                if (value > Cfg.probability)
                {
                    return;
                }
            }

            if (GroupConfig != null)
            {
                if (GroupConfig.dialog.Count > 0)
                {
                    var index = GroupConfig.dialog.Count;
                    if (index > 0)
                    {
                        index = Random.Range(0, index);
                    }

                    var text = BattleConfigManager.GetLangText(GroupConfig.dialog[index]);
                    if (text != String.Empty)
                    {
                        battleUnit.ShowChatBubble(text, 1, 1);
                    }
                }
            }

            bubbleTimer = TimeManager.time;
        }

        public virtual void OnReset()
        {
            UnitID = 0;
            Cfg = null;
            BubbleType = EBubbleEventType.None;
        }
    }

    public class KillBubble : BubbleEvent
    {
        float KillNumber;
        float targetNumber;
        float timeLimit;
        float lastTimer;
        bool initSuc = false;

        public override void InitData(int unitID, HeroBubbleEventConfig EventCfg, HeroBubbleGroupConfig cfg)
        {
            base.InitData(unitID, EventCfg, cfg);
            if (EventCfg.param.Count > 1)
            {
                timeLimit = EventCfg.param[0];
                targetNumber = EventCfg.param[1];
                initSuc = true;
            }
            else
            {
                BattleDebug.LogError("BubbleEvent 初始化失败 id： " + EventCfg.id);
            }
        }

        public override void OnTrigger(params object[] args)
        {
            if (initSuc == false)
            {
                return;
            }

            var curTime = TimeManager.time;
            var deltaTime = curTime - lastTimer;
            if (deltaTime > timeLimit)
            {
                KillNumber = 1;
            }
            else
            {
                KillNumber++;
            }

            lastTimer = curTime;
            if (KillNumber >= targetNumber)
            {
                lastTimer = 0;
                KillNumber = 0;
                Bubble();
            }
        }

        public override void OnReset()
        {
            base.OnReset();
            initSuc = false;
            KillNumber = 0;
            timeLimit = 0;
            lastTimer = 0;
        }
    }

    public class CuredBubble : BubbleEvent
    {
        float triggerValue;

        public override void InitData(int unitID, HeroBubbleEventConfig EventCfg, HeroBubbleGroupConfig cfg)
        {
            base.InitData(unitID, EventCfg, cfg);
            if (EventCfg.param.Count > 0)
            {
                triggerValue = EventCfg.param[0];
            }
            else
            {
                BattleDebug.LogError("BubbleEvent 初始化失败 id： " + EventCfg.id);
            }
        }

        public override void OnReset()
        {
            base.OnReset();
            triggerValue = 0;
        }

        public override void OnTrigger(params object[] args)
        {
            var value = (float)args[0];
                if (value >= triggerValue)
                {
                    Bubble();
                }
        }
    }

    public class HpReduceBubble : BubbleEvent
    {
        private float hpPre = 0;
        private bool tr = false;

        public override void InitData(int unitID, HeroBubbleEventConfig EventCfg, HeroBubbleGroupConfig cfg)
        {
            base.InitData(unitID, EventCfg, cfg);
            if (EventCfg.param.Count > 0)
            {
                hpPre = EventCfg.param[0];
            }
        }

        public override void OnReset()
        {
            base.OnReset();
            tr = false;
            hpPre = 0;
        }

        public override void OnTrigger(params object[] args)
        {
            var cur = (float)args[0];
            if (tr == false)
            {
                if (cur <= hpPre)
                {
                    Bubble();
                    tr = true;
                }
            }
            else
            {
                if (cur > hpPre)
                {
                    tr = false;
                }
            }
        }
        
    }

    public class StopMoveEvent : BubbleEvent
    {
        private float triggerTime;
        public override void InitData(int unitID, HeroBubbleEventConfig EventCfg, HeroBubbleGroupConfig cfg)
        {
            base.InitData(unitID, EventCfg, cfg);
            if (EventCfg.param.Count > 0)
            {
                triggerTime = EventCfg.param[0];
            }
        }

        public override void OnTrigger(params object[] args)
        {
            if (triggerTime <= 0)
            {
                return;
            }

            var curTime = (float)args[0] ;
            if (curTime > triggerTime)
            {
                Bubble();
            }
        }
    }

    public class RecevieDmgBubble : BubbleEvent
    {
        private float cfgValue = 0;

        public override void InitData(int unitID, HeroBubbleEventConfig EventCfg, HeroBubbleGroupConfig cfg)
        {
            base.InitData(unitID, EventCfg, cfg);
            if (EventCfg.param.Count > 0)
            {
                cfgValue = EventCfg.param[0];
            }
            else
            {
                BattleDebug.LogError("BubbleEvent 初始化失败 id： " + EventCfg.id);
            }
        }

        public override void OnReset()
        {
            base.OnReset();
            cfgValue = 0;
        }

        public override void OnTrigger(params object[] args)
        {
                var arg = (float)args[0];
                if (arg >= cfgValue)
                {
                    Bubble();
                }
        }
    }


    public class MissBubble : BubbleEvent
    {
        public override void OnTrigger(params object[] args)
        {
            Bubble();
        }
    }

    public class ActiveBubble : BubbleEvent
    {
        public override void OnTrigger(params object[] args)
        {
            Bubble();
        }
    }

    public class HeroEventBubbleManager : BattleSingleton<HeroEventBubbleManager>
    {
        public Dictionary<int, Dictionary<EBubbleEventType, List<BubbleEvent>>> heroEvents =
            new Dictionary<int, Dictionary<EBubbleEventType, List<BubbleEvent>>>();

        public void Kill(int unitID, int targetUid)
        {
            this.onTriggerEvent(unitID, EBubbleEventType.Kill);
        }

        public void RecevieDamage(int unitID, float damage, float unitMaxHp)
        {
            this.onTriggerEvent(unitID, EBubbleEventType.ReceiveDmg, damage / unitMaxHp);
        }

        public void Miss(int unitID)
        {
            this.onTriggerEvent(unitID, EBubbleEventType.Miss);
        }

        public void Active(int unitID)
        {
            this.onTriggerEvent(unitID, EBubbleEventType.Active);
        }

        public void Cured(int sourceUid, int targetUid,float value, float unitMaxHp)
        {
            if (targetUid != sourceUid)
            {
                this.onTriggerEvent(targetUid, EBubbleEventType.Cured, value / unitMaxHp);
            }
        }

        public void StopTime(int unitID, float time)
        {
            this.onTriggerEvent(unitID, EBubbleEventType.StopMove, time);

        }

        public void HpReduce(int unitID, float curValue, float unitMaxHp)
        {
            this.onTriggerEvent(unitID, EBubbleEventType.HpReduce, curValue / unitMaxHp);
        }

        void onTriggerEvent(int unitID, EBubbleEventType EventType, params object[] args)
        {
            Dictionary<EBubbleEventType, List<BubbleEvent>> events = null;
            if (heroEvents.TryGetValue(unitID, out events))
            {
                var callEvents = events.GetValue(EventType);
                if (callEvents != null && callEvents.Count > 0)
                {
                    foreach (var VARIABLE in callEvents)
                    {
                        VARIABLE.OnTrigger(args);
                    }
                }
            }
        }

        public void RegisterHero(int unitID, List<Vector2Int> bubbleMap)
        {
            foreach (var item in bubbleMap)
            {
                var eventCfg = BattleConfigManager.Instance.GetHeroBubbleEventConfig(item.x);
                var groupCfg = BattleConfigManager.Instance.GetHeroBubbleGroupConfig(item.y);
                if (eventCfg == null)
                {
                    BattleDebug.LogError("HeroBubbleEventCfg 初始化失败 id： " + item.x);
                    continue;
                }

                if (groupCfg == null)
                {
                    BattleDebug.LogError("HeroBubbleGroupCfg 初始化失败 id： " + item.y);
                    continue;
                }

                var eventB = getBubbleEvent((EBubbleEventType)eventCfg.type);
                if (eventB != null)
                {
                    eventB.InitData(unitID, eventCfg, groupCfg);
                    Dictionary<EBubbleEventType, List<BubbleEvent>> typeDic = null;
                    if (!heroEvents.TryGetValue(unitID, out typeDic))
                    {
                        typeDic = new Dictionary<EBubbleEventType, List<BubbleEvent>>();
                        heroEvents.Add(unitID, typeDic);
                    }

                    List<BubbleEvent> callEvents = null;
                    if (!typeDic.TryGetValue(eventB.BubbleType, out callEvents))
                    {
                        callEvents = new List<BubbleEvent>();
                        typeDic.Add(eventB.BubbleType, callEvents);
                    }

                    callEvents.Add(eventB);
                }
            }
        }

        public void UnRegisterHero(int unitID)
        {
            if (heroEvents.ContainsKey(unitID))
            {
                heroEvents.Remove(unitID);
            }
        }

        BubbleEvent getBubbleEvent(EBubbleEventType eventType)
        {
            switch (eventType)
            {
                case EBubbleEventType.None:
                    return null;
                case EBubbleEventType.Active:
                    return ClassManager.Get<ActiveBubble>();
                case EBubbleEventType.Kill:
                    return ClassManager.Get<KillBubble>();
                case EBubbleEventType.Miss:
                    return ClassManager.Get<MissBubble>();
                case EBubbleEventType.HpReduce:
                    return ClassManager.Get<HpReduceBubble>();
                case EBubbleEventType.ReceiveDmg:
                    return ClassManager.Get<RecevieDmgBubble>();
                case EBubbleEventType.Cured:
                    return ClassManager.Get<CuredBubble>();
                case EBubbleEventType.StopMove:
                    return  ClassManager.Get<StopMoveEvent>();
                default:
                    return null;
            }
        }

        public override void Dispose()
        {
            base.Dispose();
            heroEvents.Clear();
        }
    }
}